const _toString = Object.prototype.toString,
  _hasOwnProperty = Object.prototype.hasOwnProperty,
  indexOf = Array.prototype.indexOf,
  slice = Array.prototype.slice,
  _isArray = Array.prototype.isArray,
  forEach = Array.prototype.forEach,
  bind = Function.prototype.bind

export function isUndefined(obj) {
  return obj === void 0
}

export function isString(obj) {
  return _toString.call(obj) == '[object String]'
}

export function isDate(obj) {
  return _toString.call(obj) == '[object Date]'
}

export function isBoolean(obj) {
  return _toString.call(obj) == '[object Boolean]'
}

export function isNumber(obj) {
  return _toString.call(obj) == '[object Number]' && /[\d\.]+/.test(String(obj))
}

export function isJSONString(str) {
  try {
    JSON.parse(str)
  } catch (e) {
    return false
  }
  return true
}

export function isObject(obj) {
  if (obj == null) {
    return false
  } else {
    return _toString.call(obj) === '[object Object]'
  }
}

export function isPlainObject(obj) {
  return _toString.call(obj) === '[object Object]'
}

export function isArray(obj) {
  return _isArray || _toString.call(obj) === '[object Array]'
}

export function isFuction(f) {
  try {
    return /^\s*\bfunction\b/.test(f)
  } catch (x) {
    return false
  }
}

export function isArguments(obj) {
  return !!(obj && _hasOwnProperty.call(obj, 'callee'))
}

export function toString(val) {
  return val == null ? '' : isArray(val) || (isPlainObject(val) && val.toString === _toString) ? JSON.stringify(val, null, 2) : String(val)
}

export { indexOf, slice, forEach, bind, _hasOwnProperty, _toString }
